package com.dongdongshop.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.dongdongshop.constant.IdWorker;
import com.dongdongshop.constant.SecKillGoodsConstant;
import com.dongdongshop.mapper.TbSeckillGoodsMapper;
import com.dongdongshop.mapper.TbSeckillOrderMapper;
import com.dongdongshop.pojo.TbAddress;
import com.dongdongshop.pojo.TbSeckillGoods;
import com.dongdongshop.pojo.TbSeckillGoodsExample;
import com.dongdongshop.pojo.TbSeckillOrder;
import com.dongdongshop.service.SeckillService;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

@Service
@org.springframework.stereotype.Service
public class SeckillServiceImpl implements SeckillService {

    @Resource
    private TbSeckillGoodsMapper tbSeckillGoodsMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    @Resource
    private TbSeckillOrderMapper tbSeckillOrderMapper;

    @Override
    public List<TbSeckillGoods> getSeckillGoods() {
        List<TbSeckillGoods> seckillGoods = redisTemplate.boundHashOps(SecKillGoodsConstant.SEC_KILL_GOODS).values();
        if (null == seckillGoods || seckillGoods.size() <= 0){
            TbSeckillGoodsExample tsge = new TbSeckillGoodsExample();
            TbSeckillGoodsExample.Criteria criteria = tsge.createCriteria();
            criteria.andStatusEqualTo("1");//1表示审核通过的
            criteria.andStockCountGreaterThan(0);//库存大于0的
            criteria.andStartTimeLessThanOrEqualTo(new Date());//当前时间大于秒杀时间的
            criteria.andEndTimeGreaterThanOrEqualTo(new Date());//当前时间小于结束间的
            List<TbSeckillGoods> tbSeckillGoods = tbSeckillGoodsMapper.selectByExample(tsge);
            tbSeckillGoods.stream().forEach(e -> {
                redisTemplate.boundHashOps(SecKillGoodsConstant.SEC_KILL_GOODS).put(e.getId(),e);
                //设置序列化
                redisTemplate.setValueSerializer(new StringRedisSerializer());
                redisTemplate.boundValueOps(e.getId().toString()).set(e.getStockCount().toString());
            });
            return tbSeckillGoods;
        }
        return seckillGoods;
    }

    @Override
    public TbSeckillGoods getSeckillGoodById(Long id) {
        TbSeckillGoods tbSeckillGoods = (TbSeckillGoods) redisTemplate.boundHashOps(SecKillGoodsConstant.SEC_KILL_GOODS).get(id);
        return tbSeckillGoods;
    }

    @Override
    public void createSeckillOrder(Long id, String username) {
        //根据id获取redis中根据id缓存的对应的秒杀商品
        TbSeckillGoods tbSeckillGoods = (TbSeckillGoods) redisTemplate.boundHashOps(SecKillGoodsConstant.SEC_KILL_GOODS).get(id);
        //查询库存
        Long stockCount = Long.parseLong(redisTemplate.boundValueOps(id.toString()).get()+"");

        //判断redis中的数据是否存在
        if (null == tbSeckillGoods){
            throw new RuntimeException("当前商品不存在");
        }

        //判断秒杀时间是否结束
        if (tbSeckillGoods.getEndTime().getTime() - new Date().getTime() <= 0){
            throw new RuntimeException("该商品秒杀时间已经结束");
        }

        //判断当前的库存
        if (stockCount <= 0){
            throw new RuntimeException("该商品的秒杀库存已清空");
        }

        //上述情况都不存在。对Redis中的商品减库存
        Long decrement = redisTemplate.boundValueOps(id.toString()).decrement();//保证原子性
        //将减完的库存返回缓存
        redisTemplate.boundHashOps(SecKillGoodsConstant.SEC_KILL_GOODS).put(id,tbSeckillGoods);
        //将数据同时同步到秒杀商品的redis中
        tbSeckillGoods.setStockCount(decrement.intValue());
        redisTemplate.boundHashOps(SecKillGoodsConstant.SEC_KILL_GOODS).put(id,tbSeckillGoods);
        //如果redis中该商品的库存为0，伤处该秒杀商品，并同步到数据库里
        if (decrement == 0){
            tbSeckillGoodsMapper.updateByPrimaryKeySelective(tbSeckillGoods);
            //删除redis
            redisTemplate.boundHashOps(SecKillGoodsConstant.SEC_KILL_GOODS).delete(id);
        }

        IdWorker idWorker = new IdWorker();
        long tbSeckillOrderId = idWorker.nextId();
        TbSeckillOrder tbSeckillOrder = new TbSeckillOrder();
        tbSeckillOrder.setId(tbSeckillOrderId);
        tbSeckillOrder.setSeckillId(tbSeckillGoods.getId());
        tbSeckillOrder.setMoney(tbSeckillGoods.getCostPrice());
        tbSeckillOrder.setUserId(username);
        tbSeckillOrder.setSellerId(tbSeckillGoods.getSellerId());
        tbSeckillOrder.setCreateTime(new Date());
        tbSeckillOrder.setStatus("0");

        // 利用mq增加order
        rocketMQTemplate.convertAndSend("secOrder", tbSeckillOrder);

    }

    @Override
    public Long getOrderId(String username) {
        return (Long) redisTemplate.boundHashOps(SecKillGoodsConstant.SEC_KILL_ORDER).get(username);
    }

    @Override
    public TbSeckillOrder getSeckillOrderById(String out_trade_no) {
        return tbSeckillOrderMapper.selectByPrimaryKey(Long.parseLong(out_trade_no));
    }

    @Override
    public int updateSeckillOrderStatus(TbSeckillOrder tbSeckillOrder) {
        tbSeckillOrderMapper.updateByPrimaryKeySelective(tbSeckillOrder);
        return 1;
    }

    @Override
    public int insertSecOrderAddress(TbAddress tbAddress,Long id) {
        TbSeckillOrder tbSeckillOrder = new TbSeckillOrder();
        tbSeckillOrder.setId(id);
        tbSeckillOrder.setReceiverAddress(tbAddress.getProvince() + tbAddress.getCity() + tbAddress.getTown() + tbAddress.getAddress());
        tbSeckillOrder.setReceiver(tbAddress.getContact());
        tbSeckillOrder.setReceiverMobile(tbAddress.getMobile());
        return tbSeckillOrderMapper.updateByPrimaryKeySelective(tbSeckillOrder);
    }
}
